<?php

namespace App\Eloquent;

use Cache;
use Route;

class Role extends Model
{
    /**
     * 所有角色权限缓存的 key 集合的缓存 key
     *
     * @var string
     */
    const PERMISSIONS_FOR_ROLE_CACHED_KEYS = 'permissions_for_role';

    /**
     * 默认缓存时间
     *
     * @var int
     */
    const DEFAULT_CACHE_MINUTES = 30;

    /**
     * 实例化模型时, 可批量赋值属性白名单
     *
     * @var array
     */
    protected $fillable = [
        'name', 'slug', 'description',
    ];

    /**
     * 获取当前角色缓存权限
     *
     * @return \App\Admin\Eloquent\Permission[]
     */
    public function cachedPermissions()
    {
        $cacheKey = $this->{$this->primaryKey};

        $cachedKeys = Cache::get(self::PERMISSIONS_FOR_ROLE_CACHED_KEYS, function(){
            return [];
        });

        if (! in_array($cacheKey, $cachedKeys)) {
            $cachedKeys[] = $cacheKey;

            Cache::put(self::PERMISSIONS_FOR_ROLE_CACHED_KEYS, $cachedKeys, self::DEFAULT_CACHE_MINUTES);
        }
        if(env('APP_DEBUG', false)){
            return Permission::get();
        }

        return Cache::remember(self::PERMISSIONS_FOR_ROLE_CACHED_KEYS.'_'.$cacheKey, self::DEFAULT_CACHE_MINUTES, function(){
            if ($this->isSuperAdministor()) {
                return Permission::get();
            }else {
                return Permission::get();
            }
        });
    }

    /**
     * 清空所有缓存权限
     *
     * @return void
     */
    public static function cleanCachedPermissions()
    {
        if (Cache::has(self::PERMISSIONS_FOR_ROLE_CACHED_KEYS)) {
            $cacheKeys = Cache::get(self::PERMISSIONS_FOR_ROLE_CACHED_KEYS, function(){
                return [];
            });

            foreach ($cacheKeys as $cacheKey) {
                Cache::forget(self::PERMISSIONS_FOR_ROLE_CACHED_KEYS.'_'.$cacheKey);
            }

            Cache::forget(self::PERMISSIONS_FOR_ROLE_CACHED_KEYS);
        }
    }

    /**
     * 判断角色权限
     *
     * @param  array|string $name   GET|HEADbackstage/rbac/permissions
     * @param  bool $requiredAll
     * @return bool
     *
     * 示例:
     *    $role->hasPermission('GET|HEADbackstage/rbac/permissions'); #true
     *    $role->hasPermission('GET|HEADbackstage/rbac/permissions/{permissions}'); #false
     *    $role->hasPermission(['GET|HEADbackstage/rbac/permissions', GET|HEADbackstage/rbac/permissions/{permissions}]); #true
     *    $role->hasPermission(['GET|HEADbackstage/rbac/permissions', 'GET|HEADbackstage/rbac/permissions/{permissions}', true]); #false
     */
    public function hasPermission($name, $requiredAll = false)
    {
        return true;
        if ($this->isSuperAdministor()) {
            return true;
        }
        
        if (empty($name)) {
            return false;
        }

        if (is_array($name)) {
            foreach ($name as $permissionUri) {
                $hasPermission = $this->hasPermission($permissionUri);

                if (!$requiredAll && $hasPermission) {
                    return true;
                } elseif ($requiredAll && !$hasPermission) {
                    return false;
                }
            }

            return $requiredAll;
        } else {
            foreach ($this->cachedPermissions() as $permission) {
                $newPermission = $permission->methods . $permission->uri;

                if ($newPermission == $name) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 分页模糊查询
     *
     * @param  array  $options
     * @param  int  $perPage
     * @return \App\Admin\Eloquent\Role[]
     */
    public static function paginateQuery(array $options = [], int $perPage = 15)
    {
        $query = static::query();

        if (isset($options['search']) && !empty($options['search'])) {
            $condition = '%' . $options['search'] . '%';

            $query = $query->where('name', 'like', $condition)
                           ->orWhere('slug', 'like', $condition)
                           ->orWhere('description', 'like', $condition);
        }

        return $query->orderBy('created_at', 'desc')->paginate($perPage);
    }
     
    /**
     * 获取角色菜单
     */
    public function menus()
    {
        $menus = $this->cachedPermissions()->where('is_menu', 1);

        return $this->getChildrenMenus($menus);
    }

    /**
     * 游客角色
     *
     * @return \App\Admin\Eloquent\Role
     */
    public static function guest()
    {
        return static::where('slug', 'Guest')->first();
    }

    /**
     * 递归获取子菜单及其子集菜单
     *
     * @param  \Illuminate\Support\Collection $menus
     * @param  int $pid
     * @return \Illuminate\Support\Collection
     */
    protected function getChildrenMenus($menus, $pid = null)
    {
        if (is_null($pid)) {
            $topMenus = collect();

            foreach ($menus as $menu) {
                # 如果找不到父级菜单，则此菜单为顶级菜单
                if ($menus->where('id', $menu->pid)->isEmpty()) {
                    $menu->childrenMenus = $this->getChildrenMenus($menus, $menu->id);

                    $topMenus->push($menu);
                }
            }

            return $topMenus;
        } else {
            $menusCollect = collect();

            foreach ($menus->where('pid', $pid) as $menu) {
                $menu->childrenMenus = $this->getChildrenMenus($menus, $menu->id);

                $menusCollect->push($menu);
            }

            return $menusCollect;
        }
    }

    /**
     * 当前角色是否是超级管理员
     *
     * @return bool
     */
    protected function isSuperAdministor()
    {
        return $this->slug == 'SuperAdministor';
    }

    /**
     * 获取当前路由所关联的权限
     */
    public function getCurrentPermissions(){
        $route = Route::getCurrentRoute();
        $uri = $route->getUri();
        $method=implode("|",$route->getMethods());
        return $this->cachedPermissions()->where('uri',$uri)->where('methods',$method)->first();
    }

    /**
     * 获取需要选中的菜单
     * @return [type] [description]
     */
    public function getActiveMenus(){
        $this->cleanCachedPermissions();
        $menus = $this->cachedPermissions();

        $menu=$this->getCurrentPermissions();
        return $this->getCtr($menu,$menus);
    }

    protected function getCtr($current, $menus)
    {
        $collect = collect();
        $collect->push($current);
        $parent = $menus->where('id', $current->pid)->first();
        if ($parent) {
            $collect = $this->getCtr($parent, $menus)->merge($collect);
        }

        return $collect;
    }
}